package svc

import (
	"context"
	"private-domain-overseas-service/app/business/api/internal/config"
	"private-domain-overseas-service/tools/ent"
	"private-domain-overseas-service/tools/ent/migrate"

	"private-domain-overseas-service/app/business/api/internal/middleware"
	"private-domain-overseas-service/pkg/sms"
	"private-domain-overseas-service/pkg/zkclient"

	"entgo.io/ent/dialect"
	"github.com/zeromicro/go-zero/rest"

	_ "github.com/go-sql-driver/mysql"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/redis"
)

type ServiceContext struct {
	Config             config.Config
	Orm                *ent.Client
	SmsService         *sms.SmsService
	BizRedis           *redis.Redis
	CheckAndFlushToken rest.Middleware
	ZkSyncClient       *zkclient.ZkSyncClient
}

func NewServiceContext(c config.Config) *ServiceContext {
	orm := initOrm(c)

	redisStore := redis.New(c.BizRedis.Host, redis.WithPass(c.BizRedis.Pass))

	smsClient, err := sms.NewSmsService(c.Sms.SecretId, c.Sms.SecretKey, c.Sms.SDKAppID, c.Sms.LoginTemplateID, c.Sms.ResetTemplateID)
	if err != nil {
		logx.Errorf("NewSmsService error: %v", err)
		return nil
	}

	// 初始化 ZkSyncClient
	zkSyncClient, err := zkclient.NewZkSyncClient(c.Blockchain.GethRpcURLs)
	if err != nil {
		logx.Errorf("failed to connect to zkSync: %v", err)
	}

	return &ServiceContext{
		Config:             c,
		Orm:                orm,
		SmsService:         smsClient,
		BizRedis:           redisStore,
		CheckAndFlushToken: middleware.NewCheckAndFlushTokenMiddleware(c.Auth.AccessSecret).Handle,
		ZkSyncClient:       zkSyncClient,
	}
}

// initOrm
func initOrm(c config.Config) *ent.Client {
	ops := make([]ent.Option, 0)
	if c.ShowSQL {
		ops = append(ops, ent.Debug())
	}
	client, err := ent.Open(dialect.MySQL, c.DataSource, ops...)
	if err != nil {
		logx.Errorf("ent.Open error: %v", err)
		panic(err)
	}
	if err := client.Schema.Create(context.Background(),
		migrate.WithDropColumn(false), // 删除多余的列
		migrate.WithDropIndex(false),  // 删除多余的索引
	); err != nil {
		logx.Errorf("ent.Schema.Create error: %v", err)
		panic(err)
	}

	return client
}
